package com.ruiysoft.crm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruiysoft.crm.entity.FsDirectory;
import com.ruiysoft.crm.entity.FsDirectoryEx;
import com.ruiysoft.crm.mapper.BizCallLogMapper;
import com.ruiysoft.crm.mapper.BizClientMapper;
import com.ruiysoft.crm.mapper.SysUserMapper;
import com.ruiysoft.crm.model.ApiResponseEx;
import com.ruiysoft.crm.model.entity.BizCallLog;
import com.ruiysoft.crm.model.entity.BizClient;
import com.ruiysoft.crm.model.entity.SysUser;
import com.ruiysoft.crm.service.IBizCallLogService;
import com.ruiysoft.crm.service.IFsDirectoryService;
import com.ruiysoft.crm.service.SysUserService;
import com.ruiysoft.crm.util.JackJson;
import org.freeswitch.esl.client.IEslEventListener;
import org.freeswitch.esl.client.inbound.Client;
import org.freeswitch.esl.client.inbound.InboundConnectionFailure;
import org.freeswitch.esl.client.transport.event.EslEvent;
import org.freeswitch.esl.client.transport.message.EslMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Yanghu
 * @since 2019-04-13
 */
@Service
public class BizCallLogServiceImpl extends ServiceImpl<BizCallLogMapper, BizCallLog> implements IBizCallLogService {
    private static final Logger log = LoggerFactory.getLogger(BizCallLogServiceImpl.class);
    @Autowired
    BizCallLogMapper callLogMapper;

    Client client = null;

    @Autowired
    BizClientMapper bizClientMapper;
    @Autowired
    SysUserMapper sysUserMapper;

    @Autowired
    SysUserService sysUserService;

    @Value("${fs_esl_ip}")
    String fsEslIp;

    @Value("${fs_esl_port}")
    Integer fsEslPort;

    @Value("${fs_esl_password}")
    String fsEslPassword;

    @Value("${fs_record_path}")
    String fsRecordPath;

    @Value("${fs_nginx_url}")
    String fsNginxUrl;

    @PostConstruct
    public void init(){
        client = inBand();
    }

    @Override
    public Page getCallLogs(Map<String, Object> params,int userId) {
        int current= Integer.parseInt((String)params.get("current"));
        int pageSize= Integer.parseInt((String)params.get("pageSize"));
        params.remove("current");
        params.remove("pageSize");
        Page<BizCallLog> page = new Page<BizCallLog>(current, pageSize);
        page.setDesc("createDate");
        String one= (String) params. get("one");

//        if("1".equals(one)){ //查询个人的
//            params.put("createId",userId);
//        }

        params.remove("one");
        page.setRecords(callLogMapper.getCallLogs(page,params));
        return page;
    }

    @Override
    public Object updateCallLog(BizCallLog callLog) {
        return updateById(callLog);
    }

    @Override
    public ApiResponseEx insertCallLog(BizCallLog callLog) {
        ApiResponseEx responseEx = new ApiResponseEx();
        boolean i = true;
        try {
            i = save(callLog);
            if (i) {
                responseEx.setCode(200);
                responseEx.setStatus("保存成功");
                responseEx.setData(i);
            } else {
                responseEx.setCode(500);
                responseEx.setStatus("没有保存数据");
            }
        } catch (Exception ex) {
            responseEx.setCode(500);
            responseEx.setStatus(ex.getMessage());
        }
        return responseEx;
    }

    @Override
    public ApiResponseEx deleteCallLog(int id) {
        ApiResponseEx responseEx = new ApiResponseEx();
        boolean i = true;
        try {
            i = removeById(id);
            responseEx.setStatus("删除成功");
            responseEx.setCode(200);
        } catch (Exception ex) {
            responseEx.setCode(500);
            responseEx.setStatus(ex.getMessage());
        }
        return responseEx;
    }

    @Override
    public ApiResponseEx talkTimeLogByUserId(int userId) {

        return null;
    }

   /* @Override
    public Page<CustomerAndCarInfo> queryCustomerAndCars(Page page, String userId) {

        List<CustomerAndCarInfo> customerAndCarInfos = this.baseMapper.queryCustomerAndCars(page, userId);
        for (CustomerAndCarInfo customerAndCarInfo : customerAndCarInfos) {
            int clientId = customerAndCarInfo.getClientId();
            List<BizClientSteps> clientSteps = null;
            try {
                clientSteps = bizClientStepsService.getCustomerSteps(clientId);
            } catch (Exception e) {
                e.printStackTrace();
            }
            customerAndCarInfo.setSteps(clientSteps);
        }
        return page.setRecords(customerAndCarInfos);

    }*/

//    private static String host = "47.104.90.133";
////    private static int port = 7022;
////    private static String password = "Suitang8900!";

    public Client inBand() {
        Client client = new Client();
        try {
            client.connect(fsEslIp, fsEslPort, fsEslPassword, 20);
            System.out.println("esl 服务连接成功");

        } catch (InboundConnectionFailure e) {
            log.error("Connect failed", e);
            return null;
        }

        // 注册事件处理程序
        client.addEventListener(new IEslEventListener() {
            @Override
            public void eventReceived(EslEvent event) {
                try {
                    Map<String, String> map = event.getEventHeaders();
                    String uuid = map.get("variable_bridge_uuid");
                    if (event.getEventName().equals("RECORD_START")) {
                        String startTime = event.getEventDateLocal();

                        String filePath = map.get("Record-File-Path").replace(fsRecordPath,"/mp3/");

                        BizCallLog callLog = new BizCallLog();
                        callLog.setCallTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(startTime));
                        callLog.setMediaFormat("wav");

                        callLog.setMediaUrl(fsNginxUrl + filePath);
                        System.out.println("mediaUrl: " + callLog.getMediaUrl());

                        UpdateWrapper<BizCallLog> updateWrapper = new UpdateWrapper<>();
                        updateWrapper.eq("channel_uuid", uuid);
                        callLogMapper.update(callLog, updateWrapper);
                    }
                    if (event.getEventName().equals("RECORD_STOP")) {
                        log.info("RECORD_STOP：" + JackJson.fromObjectToJson(event));
                        String endTime = event.getEventDateLocal();
                        String exNumber = map.get("Caller-Caller-ID-Number");
                        String destNumber = map.get("variable_sip_to_user");
                        int talkTime = Integer.parseInt(map.get("variable_record_seconds"));
                        if(talkTime == 0){
                            BizCallLog tmp = callLogMapper.selectOne(new QueryWrapper<BizCallLog>().eq("channel_uuid",uuid));
                            talkTime = (int)(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(endTime).getTime() - tmp.getCreateDate().getTime())/1000;
                        }
                        BizCallLog callLog = new BizCallLog();
                        callLog.setCallNo(destNumber);
                        callLog.setTalkTime(talkTime);
                        callLog.setExtensionNumber(exNumber);
                        UpdateWrapper<BizCallLog> updateWrapper = new UpdateWrapper<>();
                        updateWrapper.eq("channel_uuid", uuid);
                        callLogMapper.update(callLog, updateWrapper);
                    }
                }catch (Exception ex){
                    ex.printStackTrace();
                }
//                if (event.getEventName().equals("CHANNEL_HANGUP_COMPLETE")) {
//
//                    try {
//
//                        //System.out.println(map);
//                        String success = map.get("variable_originate_disposition");
//                        if (StringUtils.equals(success, "SUCCESS")) {
//
//                            System.out.println("CHANNEL_HANGUP_COMPLETE");
//                            System.out.println(uuid);
//                            String startTime = map.get("variable_start_stamp");
//                            String endTime = event.getEventDateLocal();
//                            String exNumber = map.get("Caller-Caller-ID-Number");
//                            String destNumber = map.get("variable_sip_to_user");
//                            //                           System.err.println("CHANNEL_HANGUP_COMPLETE"); // 挂机完成事件
//                            if (null != startTime && null != endTime) {
////                                int talkTime = (int) (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(endTime).getTime() - new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(startTime).getTime()) / 1000;
//                                int talkTime = Integer.parseInt(map.get("variable_record_ms")) / 1000;
//                                BizCallLog callLog = new BizCallLog();
//                                callLog.setCallNo(destNumber);
//                                callLog.setCallTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(startTime));
//                                callLog.setTalkTime(talkTime);
//                                callLog.setExtensionNumber(exNumber);
//                                callLog.setMediaFormat("mp3");
//                                callLog.setMediaUrl("http://47.104.90.133/wav/" + uuid + ".mp3");
//                                JSONObject jsonObject = new JSONObject();
////                                callLog.setMemo(JackSon);
//                                UpdateWrapper<BizCallLog> updateWrapper = new UpdateWrapper<>();
//                                updateWrapper.eq("channel_uuid", uuid);
//                                callLogMapper.update(callLog, updateWrapper);
//                            }
//                        }
//                    } catch (Exception ex) {
//                        ex.printStackTrace();
//                    }
//                }
            }

            @Override
            public void backgroundJobResultReceived(EslEvent event) {
                // String uuid = event.getEventHeaders().get("Job-UUID");
                log.info("Background job result received+:" + event.getEventName() + "/" + event.getEventHeaders());// +"/"+JoinString(event.getEventHeaders())+"/"+JoinString(event.getEventBodyLines()));
            }
        });

        client.setEventSubscriptions("plain", "all");
        return client;
    }

    @Autowired
    IFsDirectoryService directoryService;

    @Override
    public ApiResponseEx call(Integer clientId, Integer userId, Integer tag) {
        BizClient bizClient = bizClientMapper.selectById(clientId);
        String destNumber = tag == 1 ? bizClient.getMobilePhone() : bizClient.getStandbyMobile();
        SysUser sysUser = sysUserMapper.selectById(userId);
//        String extensionNumber = sysUser.getExtentionNumber();
        FsDirectoryEx fsDirectoryEx = directoryService.getByIdLeftJoinGateWay(sysUser.getExtentionId());

        if (client == null || !client.canSend()) {
            client = inBand();
        }
        String channel_uuid = "";
        if (client != null && client.canSend()) {
            String command = "originate {ignore_early_media=false}[leg_direction=A]user/" + fsDirectoryEx.getExtention()
                    + " &bridge({execute_on_answer='record_session "
                    + fsRecordPath + UUID.randomUUID().toString()+".mp3'}[leg_direction=B]sofia/gateway/" + fsDirectoryEx.getGateway() + "/" + destNumber + ")";
            //command = "originate user/1009 &echo";

//            String command = "originate user/" + extensionNumber + " &bridge(sofia/gateway/pstn/" + destNumber + ")";
            command = "originate user/1009 &bridge(sofia/gateway/pstn1/18610348075)";
            log.info("呼叫命令【{}】", command);
            EslMessage response = client.sendSyncApiCommand(command, "");
            List<String> list = response.getBodyLines();
            log.info("呼叫返回结果:【{}】", list);
            if (list.size() > 0) {
                channel_uuid = list.get(0);
                Map retMap = new HashMap();
                if (channel_uuid.indexOf("OK") > 0) {
                    channel_uuid = channel_uuid.split(" ")[1];
                    retMap.put("uuid", channel_uuid);
                    BizCallLog callLog = new BizCallLog();
                    callLog.setChannelUuid(channel_uuid);
                    callLog.setClientId(clientId);
                    callLog.setCallNo(destNumber);
                    callLog.setCreateId(userId);
                    callLog.setEnterpriseId(sysUser.getEnterpriseId());
                    callLog.setCreateDate(new Date());
                    callLogMapper.insert(callLog);
                    retMap.put("id", callLog.getId());
                    return new ApiResponseEx(retMap);
                }
//                    command = "uuid_setvar " + channel_uuid + " record_stereo false";
//                    //log.debug("呼叫命令：【{}】", command);
//                    response = client.sendSyncApiCommand(command, "");
//                    list = response.getBodyLines();
//                     log.debug("呼叫返回结果:【{}】", list);
//                    String recordPath = "c:/wav/";
//                    command = "uuid_record " + channel_uuid + " start " + recordPath
//                            + channel_uuid + ".mp3";
//                    log.debug("呼叫录音命令：【{}】", command);
//                    response = client.sendSyncApiCommand(command, "");
//                    list = response.getBodyLines();
//                    log.debug("呼叫录音结果:【{}】", list);
//                    if (list != null && list.size() > 0) {
//                        if (list.get(0).indexOf("OK") > 0) {
//                            log.info("呼叫成功");
//                        }
//                    }
//                    return new ApiResponseEx(retMap);
//                }
//            }
            }
        }
        return ApiResponseEx.error(channel_uuid, 201);
    }

    @Override
    public List<SysUser> callTimeLog(int userId) {
        SysUser sysUser = sysUserService.getById(userId);
        List<SysUser> users = sysUserMapper.getUsersByParentId(sysUser.getDeptId());
        return users;
    }

    @Override
    public ApiResponseEx callme(Integer userId) {
        SysUser sysUser = sysUserMapper.selectById(userId);
        FsDirectoryEx fsDirectoryEx = directoryService.getByIdLeftJoinGateWay(sysUser.getExtentionId());
        if(fsDirectoryEx == null) {
            return ApiResponseEx.error("分机号未绑定，请重新设置分机号！", 200);
        }

        if (client == null || !client.canSend()) {
            client = inBand();
        }
        String channel_uuid = "";
        if (client != null && client.canSend()) {
            String command = "originate {ignore_early_media=false}[leg_direction=A]user/" + fsDirectoryEx.getExtention()
                    + " &bridge({execute_on_answer='record_session "
                    + fsRecordPath + UUID.randomUUID().toString()+".mp3'}[leg_direction=B]sofia/gateway/" + fsDirectoryEx.getGateway() + "/" + sysUser.getPhone() + ")";

            log.info("呼叫命令【{}】", command);
            EslMessage response = client.sendSyncApiCommand(command, "");
            List<String> list = response.getBodyLines();
            log.info("呼叫返回结果:【{}】", list);
            if (list.size() > 0) {
                channel_uuid = list.get(0);
                Map retMap = new HashMap();
                if (channel_uuid.indexOf("OK") > 0) {
                    channel_uuid = channel_uuid.split(" ")[1];
                    retMap.put("uuid", channel_uuid);
                    BizCallLog callLog = new BizCallLog();
                    callLog.setChannelUuid(channel_uuid);
                    callLog.setClientId(null);
                    callLog.setCallNo(sysUser.getPhone());
                    callLog.setCreateId(userId);
                    callLog.setEnterpriseId(sysUser.getEnterpriseId());
                    callLog.setCreateDate(new Date());
                    callLogMapper.insert(callLog);

                    retMap.put("id", callLog.getId());
                    return new ApiResponseEx(retMap);
                }
            }
        }

        return ApiResponseEx.error(channel_uuid, 201);
    }

}
